﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using Framework.Data.DataBroker;
using Framework.Data.Security;
using Framework.Data.Core;
//
//Description : Classe de base pour la gestion des données
//Auteur : Marc-Eric Boisvert
//Date Création : 31 mars 2008
//Révisions:
//

namespace Framework.Data.DataManager
{
    public class DataEntityManager : MarshalByRefObject
    {

        #region "Membres"

        //Instance de cette classe
        protected static DataEntityManager _instance = null;
        //Objet bidon utiliser pour gérer les locks
		protected static object _lockObject = new object();
		protected IDataBroker _dataBroker = null;
		
        #endregion

        #region "Constructeurs"

        //
        //Constructeurs
        //

        private DataEntityManager()
        {
        }

        #endregion

        #region "Propriétés"

        public static DataEntityManager Instance
        {
            get
            {
                lock (_lockObject)
                {
                    if ((_instance == null))
                    {
                        _instance = new DataEntityManager();
                    }
                }
                return _instance;
            }
        }
        
        public IDataBroker DataBroker
        {
        	get{ return this._dataBroker;}
        	set{ this._dataBroker = value;}
        }

        #endregion

        #region "Méthodes"

        /// <summary>
        /// Fonction qui retourne le prochain id disponible
        /// </summary>
        /// <returns>Int32</returns>
        /// <remarks></remarks>
        public virtual long GetNextID(IDbConnection connection = null )
        {
            return this.DataBroker.GetNextID(connection);
        }

        /// <summary>
        /// Fonction qui permet de supprimer une collection d'entité
        /// </summary>
        /// <param name="collection">Collection d'entité à supprimer</param>
        /// <returns>Boolean</returns>
        /// <remarks></remarks>
        public bool Delete(IEntityCollection<object, IBaseEntity> collection, IDbConnection connection = null)
        {
            bool result = true;
            if (connection == null)
            {
                connection = this.DataBroker.Connection;
            }
            IDbTransaction transaction = connection.BeginTransaction();
            try
            {
                foreach (IBaseEntity entity in collection.Values)
                {
                    result = result & this.DataBroker.Delete(entity,connection);
                }

                if (result)
                {
                    transaction.Commit();
                }
                else
                {
                    transaction.Rollback();
                }

                return result;
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw ex;
            }

        }
        
        /// <summary>
        /// Fonction qui permet de lire une collection d'entité de la bd
        /// </summary>
        /// <param name="entityType">Type de l'entité</param>
        /// <param name="sql">Select sql</param>
        /// <param name="connection">Connection à la bd</param>
        /// <param name="fetchRowCount">Nombre d'enregistrement à extraire de la bd à chaque roundtrip</param>
        /// <returns>IEntityCollection</returns>
        /// <remarks></remarks>
        public IEntityCollection<object, IBaseEntity> GetEntityList(System.Type entityType, string sql, IDbConnection connection = null, Int32 fetchRowCount = 250)
        {
            //TODO: Valider la sécurité.
            return this.DataBroker.GetEntityList(entityType, sql, connection, fetchRowCount);
        }

        /// <summary>
        /// Fonction qui permet de lire une collection d'entité de la bd
        /// </summary>
        /// <param name="entityType">Type de l'entité</param>
        /// <returns>IEntityCollection</returns>
        /// <remarks></remarks>
        public virtual IEntityCollection<object, IBaseEntity> GetEntityList(System.Type entityType, IDbConnection connection = null , Int32 fetchRowCount = 250, Int32 rowsPerPage = 0, Int32 pageIndex = 0)
        {
            //TODO: Valider la sécurité.
            return this.GetEntityList(entityType, new List<string>(), null, connection, fetchRowCount, rowsPerPage, pageIndex);
        }

        /// <summary>
        /// Fonction qui permet de lire une collection d'entité de la bd
        /// </summary>
        /// <param name="entityType">Type de l'entité</param>
        /// <param name="filters">Filtres</param>
        /// <param name="sortOrder">String qui représente le order by</param>
        /// <param name="connection">Connection à la bd</param>
        /// <param name="fetchRowCount">Nombre d'enregistrement à extraire de la bd à chaque roundtrip</param>
        /// <param name="rowsPerPage">Nombre maximum d'enregistrement à extraire par page</param>
        /// <param name="pageIndex">Page qui doit être chargé</param>
        /// <returns>IEntityCollection</returns>
        /// <remarks></remarks>
        public IEntityCollection<object, IBaseEntity> GetEntityList(System.Type entityType, System.Collections.Generic.List<string> filters, string sortOrder, IDbConnection connection = null, Int32 fetchRowCount = 250, Int32 rowsPerPage = 0, Int32 pageIndex = 0)
        {
            //TODO: Valider la sécurité.
            return this.DataBroker.GetEntityList(entityType, filters, sortOrder, connection, fetchRowCount, rowsPerPage, pageIndex);
        }

        /// <summary>
        /// Fonction qui permet de lire une collection d'entité de la bd
        /// </summary>
        /// <param name="entityType">Type de l'entité</param>
        /// <param name="filters">Filtres</param>
        /// <returns>IEntityCollection</returns>
        /// <remarks></remarks>
        public IEntityCollection<object, IBaseEntity> GetAttachedEntityList(System.Type entityType, IBaseEntity parentEntity, string linkSchemaName, string linkTableName, System.Collections.Generic.List<string> filters, string sortOrder, IDbConnection connection = null, Int32 fetchRowCount = 250, Int32 rowsPerPage = 0, Int32 pageIndex = 0)
        {
            //TODO: Valider la sécurité.
            return this.DataBroker.GetAttachedEntityList(entityType, parentEntity, linkSchemaName, linkTableName, filters, sortOrder, connection, fetchRowCount, rowsPerPage, pageIndex);
        }

        /// <summary>
        /// Fonction qui permet de lire un entité de la bd
        /// </summary>
        /// <param name="entityType">Type de l'entité</param>
        /// <param name="id">Id</param>
        /// <returns>IBaseEntity</returns>
        /// <remarks></remarks>
        public IBaseEntity GetEntity(System.Type entityType, long id, IDbConnection connection = null)
        {
            //TODO: Valider la sécurité.
            return this.DataBroker.GetEntity(entityType, id, connection);
        }

        /// <summary>
        /// Fonction qui permet de sauvegarder une collection d'entité dans la bd
        /// </summary>
        /// <param name="collection">Collection d'entité à sauvegarder</param>
        /// <returns>Boolean</returns>
        /// <remarks></remarks>
        public bool Save(IEntityCollection<object, IBaseEntity> collection, IDbConnection connection = null)
        {
            IDbTransaction transaction = null;

            if (connection == null)
            {
                transaction = this.DataBroker.Connection.BeginTransaction();
            }
            else
            {
                transaction = connection.BeginTransaction();
            }

            bool result = true;
            try
            {
                result = this.Save(collection, transaction, connection);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw ex;
            }

            return result;
        }

        /// <summary>
        /// Fonction qui permet de sauvegarder une collection d'entité dans la bd
        /// </summary>
        /// <param name="collection">Collection d'entité à sauvegarder</param>
        /// <param name="transaction">Transaction</param>
        /// <returns>Boolean</returns>
        /// <remarks></remarks>
        public bool Save(IEntityCollection<object, IBaseEntity> collection, IDbTransaction transaction, IDbConnection connection = null)
        {
            bool result = true;
            foreach (IBaseEntity entity in collection.Values)
            {
                if (entity.IsDirty())
                {
                	result = result & this.DataBroker.Save(entity, transaction, connection);
                }
            }
            return result;
        }

        /// <summary>
        /// Fonction qui retourne une nouvelle transaction
        /// </summary>
        /// <returns>System.Data.Common.DbTransaction</returns>
        /// <remarks></remarks>
        public IDbTransaction GetNewTransaction(IDbConnection connection = null)
        {
            if (connection == null)
            {
                connection = this.DataBroker.Connection;
            }
            return connection.BeginTransaction();
        }

        #endregion

    }
}

